import axios from "axios";
import { MessageBox } from "element-ui";
import { showLoading, closeLoading } from "./loadingHelper";
import { applyCancel, removeFromReqsMap } from "./cancelHelper";

const CancelToken = axios.CancelToken;

// 需要引进BASE_URL 默认api
const BASE_URL = (window.g && window.g.BASE_URL) || "/api";
const instance = axios.create({});

instance.interceptors.request.use(
  (_config) => {
    // 添加上ng代理
    _config.url = BASE_URL + _config.url.replace(/[ ]*=[ ]*/g, "=");
    return _config;
  },
  (error) => {
    Promise.reject(error);
  }
);
instance.interceptors.response.use(
  (_response) => {
    const { status, data: responseData, statusText } = _response;
    if (status === 200) {
      const { code, msg, data } = responseData;
      if (code === 200) {
        // 返回数据
        return data;
      } else if (code === 500) {
        MessageBox({ title: "提示", message: "系统维护中，请稍后再试" });
      } else if (code === 401) {
        MessageBox({ title: "提示", message: "身份无法识别" });
      } else if (code === 402) {
        MessageBox({ title: "提示", message: "客户段地址不正确，请重新登录" });
      } else if (code === 403) {
        MessageBox({
          title: "提示",
          message: "非常抱歉，您没有权限使用该功能",
        });
      } else if (code === 404) {
        MessageBox({ title: "提示", message: "没有找到资源" });
      } else {
        MessageBox({ title: "提示", message: `请求失败，code: ${code}` });
        Promise.reject({ msg, code });
      }
    } else {
      MessageBox({ title: "提示", type: "error", message: "服务异常" });
      Promise.reject({ msg: `${statusText}`, code: status });
    }
  },
  (error) => {
    if (error.code === "ERR_CANCELED") {
      MessageBox({
        title: "提示",
        type: "error",
        message: "请勿重复提交",
        closeOnClickModal: false,
      });
    } else {
      MessageBox({ title: "提示", type: "error", message: error });
    }
    return Promise.reject(error);
  }
);
const $axios = {
  instance: instance,
  get: async (url, params = {}, config = {}, options = {}) => {
    const loading = options.loading !== false;
    loading && showLoading();
    const r = await instance
      .get(
        url,
        Object.assign(
          { emulateJSON: true, baseURL: instance.defaults.baseURL },
          config,
          {
            params: params,
          }
        )
      )
      .catch((e) => {
        closeLoading();
        throw e;
      });
    closeLoading();
    return r;
  },
  post: async (url, data = {}, config = {}, options = {}) => {
    const loading = options.loading !== false; // 是否开启loading
    const repeatCancel = options.repeatCancel !== false; // 是否开启重复请求拦截
    loading && showLoading();
    // 处理重复请求
    if (repeatCancel) {
      const source = CancelToken.source(); // 生成令牌对象
      config = Object.assign(config, { cancelToken: source.token });
      applyCancel(url, data, source);
    }
    const r = await instance
      .post(url, data, Object.assign({ emulateJSON: true }, config))
      .catch((e) => {
        closeLoading();
        // 不是通过 source.cancel() 取消的请求
        if (e.code !== "ERR_CANCELED") {
          removeFromReqsMap(url, data);
        }
        throw e;
      });
    closeLoading();
    removeFromReqsMap(url, data);
    return r;
  },
  put: async (url, data, config = {}, options = {}) => {
    const loading = options.loading !== false;
    loading && showLoading();
    const r = await instance
      .put(
        url,
        data,
        Object.assign(
          {
            emulateJSON: true,
          },
          config
        )
      )
      .catch((e) => {
        closeLoading();
        throw e;
      });
    closeLoading();
    return r;
  },
  delete: async (url, params, config = {}, options = {}) => {
    const loading = options.loading !== false;
    loading && showLoading();
    const r = await instance
      .delete(
        url,
        Object.assign(
          {
            emulateJSON: true,
          },
          config,
          { params: params }
        )
      )
      .catch((e) => {
        closeLoading();
        throw e;
      });
    closeLoading();
    return r;
  },
};

export { $axios };
